<template>
  <view class="liu-editor">
    <!-- 工具栏 -->
    <view class="scroll">
      <view class="toolsBar-view">
        <view
          class="toolsBar-item"
          :class="{ active: formats[item.name] }"
          @click="toolsBarItemClick(item)"
          v-for="(item, index) in toolbarList"
          :key="index"
        >
          <image
            style="width: 30rpx; height: 30rpx"
            :src="item.icon"
            mode=""
          ></image>
        </view>
      </view>
    </view>

    <!-- 编辑器 -->
    <editor
      id="editor"
      :show-img-resize="true"
      :show-img-size="true"
      :show-img-toolbar="true"
      :placeholder="placeholder"
      @ready="onEditorReady"
      @statuschange="onStatusChange"
    ></editor>

    <!-- 取色器 -->
    <t-color-picker
      ref="colorPicker"
      :color="color"
      @confirm="colorConfirm"
      @cancel="colorCancel"
    ></t-color-picker>
  </view>
</template>

<script>
export default {
  name: 'liu-editor',

  props: {
    // 提示信息
    placeholder: {
      type: String,
      default: '开始输入...',
    },
    // 加载文字提示
    loadingText: {
      type: String,
      default: '上传中...',
    },
    // 上传图片时是否使用加载
    isLoading: {
      type: Boolean,
      default: true,
    },
    // 图片上传路径
    uploadImgUrl: {
      type: String,
      default: '',
    },
    // 上传的配置参数
    uploadConfig: {
      type: Object,
      default: () => ({}),
    },
    // 初始化文本信息
    html: {
      type: String,
      default: '',
    },
  },

  data() {
    return {
      editorCtx: null, // 富文本上下文api
      formats: {}, // 点前选择的样式集

      // 工具栏
      toolbarList: [
        {
          name: 'image', // 图片上传
          icon: '/static/editor-img/image.png',
          type: 'upload', // 上传类型
        },
        {
          name: 'previewFun', // 预览
          icon: '/static/editor-img/preview.png',
          type: 'click', // 点击类型
        },
        {
          name: 'header', // 文字标题(header)
          icon: '/static/editor-img/header.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '一级标题',
              value: 'H1',
            },
            {
              name: '二级标题',
              value: 'H2',
            },
            {
              name: '三级标题',
              value: 'H3',
            },
            {
              name: '四级标题',
              value: 'H4',
            },
            {
              name: '五级标题',
              value: 'H5',
            },
            {
              name: '六级标题',
              value: 'H6',
            },
          ],
        },
        {
          name: 'bold', // 文字加粗(bold)
          icon: '/static/editor-img/bold.png',
          type: 'click', // 点击类型
        },
        {
          name: 'italic', // 文字斜体(italic)
          icon: '/static/editor-img/italic.png',
          type: 'click', // 点击类型
        },
        {
          name: 'underline', // 文字下划线(underline)
          icon: '/static/editor-img/underline.png',
          type: 'click', // 点击类型
        },
        {
          name: 'strike', // 文字删除线(strike)
          icon: '/static/editor-img/strike.png',
          type: 'click', // 点击类型
        },
        {
          name: 'indent', // 文字缩进(indent)
          icon: '/static/editor-img/indent.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '向右缩进',
              value: '+1',
            },
            {
              name: '向左缩进',
              value: '-1',
            },
          ],
        },
        {
          name: 'list', // 列表(list)
          icon: '/static/editor-img/list.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '有序列表',
              value: 'ordered',
            },
            {
              name: '无序列表',
              value: 'bullet',
            },
            {
              name: '方框列表',
              value: 'check',
            },
          ], // 数字 、点、方框
        },
        {
          name: 'lineHeight', // 文字行高(lineHeight)
          icon: '/static/editor-img/lineHeight.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '1',
              value: '1',
            },
            {
              name: '1.5',
              value: '1.5',
            },
            {
              name: '2',
              value: '2',
            },
            {
              name: '2.5',
              value: '2.5',
            },
            {
              name: '3',
              value: '3',
            },
          ],
        },
        {
          name: 'fontSize', // 文字大小(fontSize)
          icon: '/static/editor-img/fontSize.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '10px',
              value: '10px',
            },
            {
              name: '13px',
              value: '13px',
            },
            {
              name: '16px',
              value: '16px',
            },
            {
              name: '18px',
              value: '18px',
            },
            {
              name: '24px',
              value: '24px',
            },
            {
              name: '32px',
              value: '32px',
            },
            {
              name: '48px',
              value: '48px',
            },
          ],
        },
        {
          name: 'align', // 文字排版(align)
          icon: '/static/editor-img/align.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '左对齐',
              value: 'left',
            },
            {
              name: '居中对齐',
              value: 'center',
            },
            {
              name: '右对齐',
              value: 'right',
            },
            {
              name: '整行对齐',
              value: 'justify',
            },
          ],
        },
        {
          name: 'color', // 文字颜色(color)
          icon: '/static/editor-img/color.png',
          type: 'popup', // 弹窗类型
        },
        {
          name: 'undoFun', // 撤销
          icon: '/static/editor-img/undo.png',
          type: 'click', // 点击类型
        },
        {
          name: 'redoFun', // 恢复
          icon: '/static/editor-img/redo.png',
          type: 'click', // 点击类型
        },
        {
          name: 'margin', // 外边距(margin)
          icon: '/static/editor-img/margin.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '四周外边距',
              value: 'margin',
            },
            {
              name: '上外边距',
              value: 'marginTop',
            },
            {
              name: '下外边距',
              value: 'marginBottom',
            },
            {
              name: '左外边距',
              value: 'marginLeft',
            },
            {
              name: '右外边距',
              value: 'marginRight',
            },
          ],
        },
        {
          name: 'padding', // 内边距(padding)
          icon: '/static/editor-img/padding.png',
          type: 'select', // 选择类型
          value: [
            {
              name: '四周内边距',
              value: 'padding',
            },
            {
              name: '上内边距',
              value: 'paddingTop',
            },
            {
              name: '下内边距',
              value: 'paddingBottom',
            },
            {
              name: '左内边距',
              value: 'paddingLeft',
            },
            {
              name: '右内边距',
              value: 'paddingRight',
            },
          ],
        },
        {
          name: 'clearFun', // 清空编辑器内容
          icon: '/static/editor-img/clear.png',
          type: 'click', // 选择类型
        },
      ],

      // color
      color: {
        r: 255,
        g: 0,
        b: 0,
        a: 0.6,
      },
    }
  },

  watch: {
    html(n, o) {
      n && this.onEditorReady()
    },
  },

  methods: {
    // 取色器确定事件
    colorConfirm(e) {
      // console.log(e);
      this.format('color', e.hex)
    },
    // 取色器取消事件
    colorCancel() {
      // console.log('取消');
    },

    // 初始化
    onEditorReady() {
      if (this.editorCtx) {
        this.html && this.initEditor()
        return
      }
      uni
        .createSelectorQuery()
        .select('#editor')
        .context((res) => {
          if (res.context) {
            this.editorCtx = res.context
            this.html && this.initEditor()
          }
        })
        .exec()
    },

    // 设置样式时触发
    onStatusChange(e) {
      this.formats = e.detail
    },

    // 设置样式
    format(name, value) {
      this.editorCtx.format(name, value)
    },

    // 插入图片
    insertImage() {
      uni.chooseImage({
        success: async (res) => {
          // console.log(res);
          // res.tempFilePaths
          if (res.tempFilePaths.length) {
            // console.log(res.tempFilePaths);
            // 加载
            this.isLoading &&
              uni.showLoading({ title: this.loadingText, mask: true })

            for (let i = 0, ilen = res.tempFilePaths.length; i < ilen; i++) {
              try {
                let [err, img_res] = await this.uploadImageSync(
                  res.tempFilePaths[i]
                )
                let resData = JSON.parse(img_res.data)
                // console.log(resData);
                if (!resData.error_code) {
                  uni.hideLoading()
                  this.editorCtx.insertImage({
                    src: resData.data.uri,
                    alt: '图片',
                    extClass: 'editor--editor-img',
                    // width:'100%',
                  })
                  this.editorCtx.insertText({ text: ' ' })
                } else {
                  uni.hideLoading()
                  this.toast('图片上传失败')
                }
              } catch (e) {
                //TODO handle the exception
                uni.hideLoading()
                this.toast('上传图片发生错误')
              }
            }
            // console.log(1122);
          }
        },
        fail: (err) => {
          console.log(err)
        },
      })
    },

    // 初始化文本信息
    initEditor() {
      this.editorCtx.setContents({ html: this.html })
    },

    // 图片上传
    uploadImageSync(filePath) {
      // 没有上传路径 直接返回 filePath
      if (!this.uploadImgUrl) {
        return filePath
      }
      let header = this.uploadConfig.header || {}
      let formData = this.uploadConfig.formData || {}
      // 返回 promise对象
      return uni.uploadFile({
        url: this.uploadImgUrl,
        filePath,
        header: {
          // #ifdef APP-PLUS
          'content-type': 'multipart/form-data',
          // #endif
          ...header,
        },
        // #ifdef APP-PLUS
        name: 'file',
        // #endif
        formData,
      })
    },

    // 轻提示
    toast(title, duration = 1000, icon = 'none') {
      uni.showToast({ title, duration, icon })
    },

    // 工具栏点击事件
    toolsBarItemClick(item) {
      let switchFun = {
        // 点击类型
        click: () => {
          let keys = { previewFun: 1, undoFun: 1, redoFun: 1, clearFun: 1 }
          if (keys[item.name]) {
            return this[item.name] && this[item.name]()
          }
          this.format(item.name, item.value)
        },
        // 弹窗类型
        popup: () => {
          if (this.formats[item.name]) {
            return this.format(item.name, '')
          }
          this.$refs.colorPicker.open()
        },
        // 选择类型
        select: () => {
          if (this.formats[item.name]) {
            return this.format(item.name, '')
          }
          let keys = item.value.map((item) => item.name)
          if (item.name === 'margin' || item.name === 'padding') {
            uni.showActionSheet({
              itemList: keys,
              success: (resOne) => {
                let name = item.value[resOne.tapIndex].value
                setTimeout(() => {
                  let list = ['0px', '10px', '15px', '20px', '25px', '30px']
                  uni.showActionSheet({
                    itemList: list,
                    success: (resTwo) => {
                      this.format(name, list[resTwo.tapIndex])
                      // console.log(name,list[resTwo.tapIndex]);
                    },
                  })
                }, 100)
              },
              fail: function (res) {
                console.log(res.errMsg)
              },
            })
            return
          }
          uni.showActionSheet({
            itemList: keys,
            success: (res) => {
              this.format(item.name, item.value[res.tapIndex].value)
            },
            fail: function (res) {
              console.log(res.errMsg)
            },
          })
        },
        // 上传类型
        upload: () => {
          this.insertImage()
        },
      }
      switchFun[item.type] && switchFun[item.type]()
    },

    // 预览
    async previewFun() {
      // this.toast('预览');
      let res = await this.editorGetContents()
      if (res.html) {
        uni.setStorageSync('editorPreviewHtml', res.html)
      }
      uni.navigateTo({ url: '/pages/editorPreview/editorPreview' })
    },
    // 撤销
    undoFun() {
      this.toast('撤销')
      this.editorCtx.undo()
    },
    // 清空编辑器内容
    clearFun() {
      uni.showModal({
        content: '确定清空编辑器内容？',
        success: (res) => {
          if (res.confirm) {
            this.editorCtx.clear()
          }
        },
      })
    },

    // 获取编辑器内容
    editorGetContents(cb) {
      return new Promise((resolve, reject) => {
        this.editorCtx.getContents({
          success: (res) => {
            resolve(res)
          },
          fail: (err) => {
            reject(err)
          },
        })
      })
    },
  },
}
</script>

<style>
.liu-editor {
  width: 100%;
  background-color: #fff;
}

.toolsBar-view {
  display: flex;
  align-items: center;
  background-color: #f2f2f2;
  padding-left: 20rpx;
  border-bottom: 4rpx solid #e1e1e1;
}
.toolsBar-item {
  margin-right: 25rpx;
  width: 50rpx;
  height: 50rpx;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.toolsBar-item.active {
  background-color: rgba(255, 85, 0, 0.5);
}

.scroll {
  width: 100%;
  height: 80rpx;
  overflow: hidden;
  overflow-x: auto;
  display: flex;
}

#editor {
  padding: 20rpx 20rpx 20rpx;
  background-color: #f2f2f2;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  font-size: 16px;
  line-height: 1.5;
  overflow: auto;
}
</style>